home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d11 / frasrc14.arc / FRACTINT.C < prev    next >
C/C++ Source or Header  |  1990-08-02  |  67KB  |  2,054 lines

  1. /*
  2.     FRACTINT - The Ultimate Fractal Generator
  3.             Main Routine
  4. */
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <dos.h>
  10. #include <float.h>
  11. #include <process.h>
  12. #include <time.h>
  13.  
  14. #ifndef __TURBOC__
  15. #include <malloc.h>
  16. #endif
  17.  
  18. #define PUTTHEMHERE 1            /* stuff common external arrays here */
  19.  
  20. #include "fractint.h"
  21. #include "fractype.h"
  22.  
  23. int    adapter;        /* Video Adapter chosen from list in ...h */
  24.  
  25. extern struct complex initorbit;
  26. extern char useinitorbit;
  27. extern int RANDOMIZE;          /* Color randomizing factor */
  28. extern int full_color;          /* Selects full color with light source fills */
  29. extern int Ambient;          /* Darkness of shadows in light source */
  30. extern int haze;          /* Amount of haze to factor in in full color */
  31. extern char Light_Name[];     /* Name of full color .TGA file */
  32. extern unsigned char usemag;
  33. extern char potfile[];        /* potential filename */
  34. extern int video_type;        /* coded value indicating video adapter type */
  35. extern int tgaview();
  36. extern int gifview();
  37. extern void moveboxf(double,double);
  38. extern void chgboxf(double,double);
  39. extern void chgboxi(int,int);
  40. struct fractal_info save_info, read_info; /*  for saving data in file */
  41. extern int biomorph;
  42. extern int askvideo;
  43. extern int periodicitycheck;
  44. extern int forcesymmetry;
  45. extern    char    readname[];    /* name of fractal input file */
  46. extern    int    showfile;     /* has file been displayed yet? */
  47. #define FUDGEFACTOR    29        /* fudge all values up by 2**this */
  48. #define FUDGEFACTOR2    24        /* (or maybe this)          */
  49.  
  50. #define MAXHISTORY    25        /* save this many historical rcds */
  51. struct historystruct {            /* history structure */
  52.     int fractype;            /* fractal type */
  53.     double param[4];        /* parameters */
  54.     double xxmin;            /* top left    */
  55.     double yymax;            /* top left    */
  56.     double xxmax;            /* bottom right */
  57.     double yymin;            /* bottom right */
  58.     double xx3rd;            /* bottom left    */
  59.     double yy3rd;            /* bottom left    */
  60.     } far *history;
  61.  
  62. /* yes, I *know* it's supposed to be compatible with Microsoft C,
  63.    but some of the routines need to know if the "C" code
  64.    has been compiled with Turbo-C.  This flag is a 1 if FRACTINT.C
  65.    (and presumably the other routines as well) has been compiled
  66.    with Turbo-C. */
  67.  
  68. int compiled_by_turboc;
  69.  
  70. extern    char    savename[];        /* save files using this name */
  71.  
  72. extern    char preview;     /* 3D preview mode flag */
  73.  
  74. extern char floatflag;            /* floating-point fractals? */
  75.  
  76. extern    char    temp1[];            /* temporary strings        */
  77.  
  78. extern    int    debugflag;        /* internal use only - you didn't see this */
  79. /*
  80.    the following variables are out here only so
  81.    that the calcfract() and assembler routines can get at them easily
  82. */
  83.     int    dotmode;            /* video access method        */
  84.     int    oktoprint;            /* 0 if printf() won't work */
  85.     int    xdots, ydots;            /* # of dots on the screen  */
  86.     double    dxsize, dysize;         /* xdots-1, ydots-1        */
  87.     int    colors;             /* maximum colors available */
  88.     int    maxit;                /* try this many iterations */
  89.     int    boxcount;            /* 0 if no zoom-box yet     */
  90.     int    zrotate;            /* zoombox rotation        */
  91.     double    zbx,zby;            /* topleft of zoombox        */
  92.     double    zwidth,zdepth,zskew;        /* zoombox size & shape     */
  93.  
  94.     int    fractype;            /* if == 0, use Mandelbrot  */
  95.     int    numpasses;            /* 0 if single-pass, else 1 */
  96.     int    solidguessing;            /* 0 if disabled, else 1    */
  97.     long    creal, cimag;            /* real, imag'ry parts of C */
  98.     long    delx, dely;            /* screen pixel increments  */
  99.     long    delx2, dely2;            /* screen pixel increments  */
  100.     double    delxx, delyy;            /* screen pixel increments  */
  101.     double    delxx2, delyy2;         /* screen pixel increments  */
  102.     long    delmin;             /* for calcfrac/calcmand    */
  103.     double    ddelmin;            /* same as a double        */
  104.     double    param[4];            /* up to four parameters    */
  105.     double    potparam[3];        /* three potential parameters*/
  106.     long    fudge;                /* 2**fudgefactor    */
  107.     int    bitshift;            /* fudgefactor        */
  108.  
  109.     int    hasconfig;            /* = 0 if 'fractint.cfg'    */
  110.     int    diskisactive;            /* disk-video drivers flag  */
  111.     int    diskvideo;            /* disk-video access flag   */
  112.  
  113.     /* note that integer grid is set when integerfractal && !invert;    */
  114.     /* otherwise the floating point grid is set; never both at once     */
  115.     long    far *lx0, far *ly0;        /* x, y grid            */
  116.     long    far *lx1, far *ly1;        /* adjustment for rotate    */
  117.     /* note that lx1 & ly1 values can overflow into sign bit; since     */
  118.     /* they're used only to add to lx0/ly0, 2s comp straightens it out  */
  119.     double far *dx0, far *dy0;        /* floating pt equivs */
  120.     double far *dx1, far *dy1;
  121.     int    integerfractal;     /* TRUE if fractal uses integer math */
  122.  
  123. extern    int    inside;             /* inside color: 1=blue     */
  124. extern    int    outside;            /* outside color, if set    */
  125. extern    int    finattract;            /* finite attractor option  */
  126. extern    int    cyclelimit;            /* color-rotator upper limit */
  127. extern    int    display3d;            /* 3D display flag: 0 = OFF */
  128. extern    int    overlay3d;            /* 3D overlay flag: 0 = OFF */
  129. extern    int    init3d[20];            /* '3d=nn/nn/nn/...' values */
  130. extern    int    boxcolor;            /* zoom box color */
  131.  
  132. extern      int previewfactor;            /* for save_info */
  133. extern      int xtrans;
  134. extern      int ytrans;
  135. extern      int red_crop_left;
  136. extern      int red_crop_right;
  137. extern      int blue_crop_left;
  138. extern      int blue_crop_right;
  139. extern      int red_bright;
  140. extern      int blue_bright;
  141. extern      int xadjust;
  142. extern      int eyeseparation;
  143. extern      int glassestype;
  144. extern      int filetype;
  145. extern      int whichimage;
  146.  
  147.  
  148. extern unsigned char dacbox[256][3];    /* Video-DAC (filled in by SETVIDEO) */
  149. extern unsigned char olddacbox[256][3]; /* backup copy of the Video-DAC */
  150. extern int    daclearn, daccount;    /* used by the color-cyclers */
  151. extern int    extraseg;        /* used by Save-to-DISK routines */
  152. extern int    cpu;            /* cpu type            */
  153. extern int    fpu;            /* fpu type            */
  154. extern int    lookatmouse;        /* used to select mouse mode    */
  155. extern int    out_line();        /* called in decoder */
  156. extern int    cmp_line();        /* for test purposes */
  157. extern    int    outlin16();        /* called in decoder */
  158. extern int    line3d();        /* called in decoder */
  159. extern int    (*outln)();        /* called in decoder */
  160. extern    int    filetype;        /* GIF or other */
  161.  
  162. /* variables defined by the command line/files processor */
  163. extern    double    inversion[];
  164. extern    int    invert;         /* non-zero if inversion active */
  165. extern    int    initbatch;        /* 1 if batch run (no kbd)  */
  166. extern    int    initmode;        /* initial video mode        */
  167. extern    int    inititer;        /* initial value of maxiter */
  168. extern    int    initincr;        /* initial maxiter incrmnt  */
  169. extern    int    initpass;        /* initial pass mode        */
  170. extern    int    initsolidguessing;    /* initial solid-guessing md*/
  171. extern    int    initfractype;        /* initial type set flag    */
  172. extern    int    initcyclelimit;     /* initial cycle limit        */
  173. extern    int    initcorners;        /* initial flag: corners set*/
  174. extern    double    initxmin,initxmax;    /* initial corner values    */
  175. extern    double    initymin,initymax;    /* initial corner values    */
  176. extern    double    initx3rd,inity3rd;    /* initial corner values    */
  177. extern    double    initparam[4];        /* initial parameters        */
  178. extern    int    LogFlag;        /* non-zero if logarithmic palettes */
  179. extern    int    transparent[];
  180. extern    int    decomp[];
  181. extern    int    distest;        /* non-zero if distance estimator   */
  182.  
  183. extern char showbox;          /* flag to show box and vector in preview */
  184. extern char FormFileName[];   /* file to find (type=)formulas in */
  185. extern char FormName[];       /* Name of the Formula (if not null) */
  186. extern int bailout;          /* user input bailout value */
  187. extern int mapset;          /* indicates new map */
  188. extern int warn;          /* 0 if savename warnings off, 1 if on */
  189. extern unsigned initsavetime; /* timed save interval */
  190. extern char MAP_name[];       /* map file name */
  191.  
  192. extern int boundarytraceflag; /* boundary tracing (0 = off, 1 = on) */
  193.  
  194. extern int rflag, rseed;
  195. int    comparegif=0;            /* compare two gif files flag */
  196. int    timedsave=0;            /* when doing a timed save */
  197. extern long saveticks, savebase;    /* timed save vars for general.asm */
  198. extern long readticker();        /* read bios ticker */
  199. int    resave_flag=0;            /* tells encoder not to incr filename */
  200.  
  201. /* for historical reasons (before rotation):         */
  202. /*    top    left  corner of screen is (xxmin,yymax) */
  203. /*    bottom left  corner of screen is (xx3rd,yy3rd) */
  204. /*    bottom right corner of screen is (xxmax,yymin) */
  205. double    xxmin,xxmax,yymin,yymax,xx3rd,yy3rd; /* selected screen corners  */
  206. long    xmin, xmax, ymin, ymax, x3rd, y3rd;  /* integer equivs         */
  207. double    sxmin,sxmax,symin,symax,sx3rd,sy3rd; /* displayed screen corners */
  208. double    plotmx1,plotmx2,plotmy1,plotmy2;     /* real->screen multipliers */
  209.  
  210. int calc_status; /* -1 no fractal            */
  211.          /*  0 parms changed, recalc reqd   */
  212.          /*  1 actively calculating        */
  213.          /*  2 interrupted, resumable        */
  214.          /*  3 interrupted, not resumable   */
  215.          /*  4 completed            */
  216. long calctime;
  217.  
  218. static void adjust_to_limits(double);
  219. static void smallest_add(double *);
  220. static int  ratio_bad(double,double);
  221. int  key_count(int);
  222. static void move_zoombox(int);
  223. static void reset_initparms();
  224.  
  225. /* "main()" now does initialization only and then calls "main_routine()" */
  226.  
  227. void main(argc,argv)
  228. int argc;
  229. char *argv[];
  230. {
  231. long    huge *xxxalloc;             /* Quick-C klooge (extraseg) */
  232.  
  233. initasmvars();                    /* initialize ASM stuff */
  234.  
  235. hasconfig = readconfig();            /* read fractint.cfg, if any */
  236.  
  237. maxvideomode = initvideotable();        /* get the size of video table */
  238. if ( maxvideomode >= MAXVIDEOMODES)        /* that's all the Fn keys we got! */
  239.     maxvideomode = MAXVIDEOMODES;
  240.  
  241. cmdfiles(argc,argv);                /* process the command-line */
  242.  
  243. if (debugflag == 8088)              cpu =  86; /* for testing purposes */
  244. if (debugflag == 2870 && fpu >= 287 ) fpu = 287; /* for testing purposes */
  245. if (debugflag ==  870 && fpu >=  87 ) fpu =  87; /* for testing purposes */
  246. if (debugflag ==   70 && fpu >=   0 ) fpu =   0; /* for testing purposes */
  247. if (debugflag >= 9002 && debugflag <= 9100)     /* for testing purposes */
  248.     if (video_type > (debugflag-9000)/2)     /* adjust the video value */
  249.         video_type = (debugflag-9000)/2;
  250.  
  251. #ifdef __TURBOC__
  252.    compiled_by_turboc = 1;
  253. #else
  254.    compiled_by_turboc = 0;
  255. #endif
  256.  
  257. /*
  258.    This code is used for emergency purposes when we just *have* to
  259.    get CodeView working and we don't *care* about the fact that any
  260.    attempt to do something tricky like using help mode or a hi-rez
  261.    video mode will require "extraseg" memory that we just don't have.
  262.  
  263.    Note: unless and until you can get CodeView to reside *entirely* in
  264.    extended/expanded memory, run "codeview /s /e fractint debug=10000"
  265.    and don't use help or any hi-rez video modes (they require the full
  266.    92K of memory allocated to 'extraseg').
  267.  
  268.    Hopefully this code will go away when Microsoft C 6.0 is released
  269.    with a version of CodeView that resides entirely in extended/expanded
  270.    memory.
  271. */
  272.  
  273. #ifndef __TURBOC__
  274. if (debugflag == 10000 && extraseg == 0) {
  275.     xxxalloc = (long huge *)halloc(16384L,4);  /* try for 64K */
  276.     extraseg = FP_SEG(xxxalloc);
  277.     if (extraseg == 0) {
  278.         xxxalloc = (long huge *)halloc(8192L,4); /* try for 32K */
  279.         extraseg = FP_SEG(xxxalloc);
  280.         }
  281.     }
  282. #endif
  283.  
  284. if (extraseg == 0             /* oops.  not enough memory     */
  285.   || (history = (struct historystruct far * ) farmemalloc((unsigned long)
  286.     (MAXHISTORY * sizeof(*history)))) == NULL
  287.   || (ly0 = (long far *) farmemalloc(2000L)) == NULL) {
  288.     buzzer(2);
  289.     printf(" I'm sorry, but you don't have enough free memory \n");
  290.     printf(" to run this program.\n\n");
  291.     exit(1);
  292.     }
  293. farmemfree((unsigned char far *)ly0); /* that was just to check for minimal workspace */
  294.  
  295. #ifdef __TURBOC__
  296.       dx0 = MK_FP(extraseg,0);
  297. #else
  298.       FP_SEG(dx0)=extraseg;
  299.       FP_OFF(dx0)=0;
  300. #endif
  301.       dy1 = (dx1 = (dy0 = dx0 + MAXPIXELS) + MAXPIXELS) + MAXPIXELS;
  302.       lx0 = (long far *) dx0;
  303.       ly1 = (lx1 = (ly0 = lx0 + MAXPIXELS) + MAXPIXELS) + MAXPIXELS;
  304.  
  305. diskisactive = 0;            /* disk-video is inactive */
  306. diskvideo = 0;                /* disk driver is not in use */
  307. setvideomode(3,0,0,0);            /* switch to text mode */
  308. calc_status = -1;            /* no active fractal image */
  309.  
  310. if (debugflag == 10000) {        /* check for free memory */
  311.     char *tempptr;
  312.     unsigned char huge *fartempptr;
  313.     unsigned i,i2;
  314.     long j,j2;
  315.     printf("\n CPU type is %d \n\n FPU type is %d \n\n", cpu, fpu);
  316.     i = j = 0;
  317.     i2 = 0x8000;
  318.     while ((i2 >>= 1) != 0)
  319.            if ((tempptr = malloc(i+i2)) != NULL) {
  320.                free(tempptr);
  321.                i += i2;
  322.                }
  323.     printf(" %d NEAR bytes free \n", i);
  324.     j2 = 0x80000;
  325.     while ((j2 >>= 1) != 0)
  326.            if ((fartempptr = (unsigned char huge *)farmemalloc(j+j2)) != NULL) {
  327.                farmemfree((void far*)fartempptr);
  328.                j += j2;
  329.                }
  330.     printf(" %ld FAR bytes free \n\n press any key to continue...\n", j);
  331.     getakey();
  332.     }
  333.  
  334. main_routine();
  335.  
  336. }
  337.  
  338. /* "main_routine" is the main-command-level traffic cop */
  339.  
  340. main_routine()
  341. {
  342.     double    jxxmin, jxxmax, jyymin, jyymax; /* "Julia mode" entry point */
  343.     double    jxx3rd, jyy3rd;
  344.     int    frommandel;            /* if julia entered from mandel */
  345.     double    atof(), ftemp;            /* floating point stuff    */
  346.     double    ccreal,ccimag;            /* Julia Set Parameters    */
  347.     int    axmode, bxmode, cxmode, dxmode; /* video mode (BIOS ##) */
  348.     int    historyptr;            /* pointer into history tbl */
  349.     int    zoomoff;            /* = 0 when zoom is disabled */
  350.     int    kbdchar;            /* keyboard key-hit value */
  351.     int    more, kbdmore;            /* continuation variables */
  352.     int    i, j, k, l;            /* temporary loop counters */
  353.     int    displaypage;            /* signon display page        */
  354.     int    savedac;            /* save-the-Video DAC flag  */
  355.     int    olddotmode;            /* temp copy of dotmode     */
  356.     int    status;
  357.  
  358. savedac = 0;                /* don't save the VGA DAC */
  359. historyptr = 0;             /* initialize history ptr */
  360. history[historyptr].fractype = -1;
  361.  
  362. restorestart:
  363.  
  364. lookatmouse = 0;            /* ignore mouse */
  365.  
  366. read_overlay();             /* read overlay/3D files, if reqr'd */
  367.  
  368. if (overlay3d && initmode < 0) {    /* overlay command failed */
  369.     setforgraphics();        /* restore the graphics screen */
  370.     overlay3d = 0;            /* forget overlays */
  371.     display3d = 0;            /* forget 3D */
  372.     if (calc_status > 0)
  373.         calc_status = 0;
  374.     goto resumeloop;        /* ooh, this is ugly */
  375.     }
  376.  
  377.  
  378. restart:                /* insert key re-starts here */
  379.  
  380. savedac = 0;                /* don't save the VGA DAC */
  381.  
  382. if (*readname==0 || showfile)
  383.     if (calc_status > 0)        /* goto restart implies re-calc */
  384.         calc_status = 0;
  385.  
  386. if (initbatch == 0)
  387.     lookatmouse = -1073;        /* just mouse left button, == pgup */
  388.  
  389. maxit = inititer;                /* max iterations */
  390. numpasses = initpass-1;             /* single/dual-pass mode */
  391. solidguessing = initsolidguessing;        /* solid-guessing mode */
  392.  
  393. fractype = initfractype;            /* use the default set     */
  394.  
  395. if (distest)
  396.     floatflag = 1;
  397.  
  398. if (floatflag) {                /* adjust for floating pt */
  399.     if (fractalspecific[fractype].isinteger != 0 &&
  400.         fractalspecific[fractype].tofloat != NOFRACTAL)
  401.         fractype = fractalspecific[fractype].tofloat;
  402.     }
  403. else    {
  404.     if (fractalspecific[fractype].isinteger == 0 &&
  405.         fractalspecific[fractype].tofloat != NOFRACTAL)
  406.         fractype = fractalspecific[fractype].tofloat;
  407.     }
  408.  
  409. cyclelimit = initcyclelimit;            /* default cycle limit     */
  410. for (i = 0; i < 4; i++)
  411. {
  412.    if(initparam[i] != FLT_MAX)
  413.    {
  414.       param[i] = initparam[i];/* use the default params*/
  415.       fractalspecific[fractype].paramvalue[i] = param[i];
  416.    }
  417.    else
  418.       initparam[i] = param[i] = fractalspecific[fractype].paramvalue[i];
  419. }
  420. ccreal = param[0]; ccimag = param[1];        /* default C-values     */
  421. xxmin = initxmin; xxmax = initxmax;        /* default corner values */
  422. yymin = initymin; yymax = initymax;        /* default corner values */
  423. xx3rd = initx3rd; yy3rd = inity3rd;        /* default corner values */
  424. if (fractalspecific[fractype].flags&NOROTATE != 0) {
  425.    /* ensure min<max and unrotated rectangle */
  426.    if (xxmin > xxmax) { ftemp = xxmax; xxmax = xxmin; xxmin = ftemp; }
  427.    if (yymin > yymax) { ftemp = yymax; yymax = yymin; yymin = ftemp; }
  428.    xx3rd = xxmin; yy3rd = yymin;
  429. }
  430.  
  431. /* set some reasonable limits on the numbers (or the algorithms will fail) */
  432.  
  433. if(fractalspecific[fractype].isinteger > 1)
  434.    bitshift = fractalspecific[fractype].isinteger;
  435. else
  436.    bitshift = FUDGEFACTOR2;            /* shift bits by this much */
  437.  
  438. if(fractalspecific[fractype].isinteger == 0) /* TW start */
  439. {
  440.    if((i = fractalspecific[fractype].tofloat) != NOFRACTAL)
  441.       if(fractalspecific[i].isinteger > 1)
  442.      bitshift =  fractalspecific[i].isinteger; /* TW stop */
  443. }
  444.  
  445. if (fractype == MANDEL || fractype == JULIA) {    /* adust shift bits if.. */
  446.    if (fabs(potparam[0]) < .0001        /* not using potential */
  447.        && (fractype != MANDEL ||        /* and not an int mandel */
  448.        (ccreal == 0.0 && ccimag == 0.0))    /*  w/ "fudged" parameters */
  449.        && ! invert                /* and not inverting */
  450.        && biomorph == -1            /* and not biomorphing */
  451.        && debugflag != 1234)            /* and not debugging */
  452.        bitshift = FUDGEFACTOR;
  453.    if (ccreal < -1.99 || ccreal > 1.99) ccreal = 1.99;
  454.    if (ccimag < -1.99 || ccimag > 1.99) ccimag = 1.99;
  455.    }
  456.  
  457. fudge = 1; fudge = fudge << bitshift;           /* fudged value for printfs */
  458.  
  459. frommandel = 0;
  460.  
  461. adapter = initmode;            /* set the video adapter up    */
  462. initmode = -1;                /* (once)            */
  463.  
  464. helpmode = HELPAUTHORS;            /* use this help mode */
  465. if (adapter < 0) {
  466.     calc_status = -1;        /* no active fractal image */
  467.     help();             /* display the credits screen */
  468. }
  469. helpmode = HELPMENU;               /* now use this help mode */
  470.  
  471. while (adapter < 0) {            /* cycle through instructions    */
  472.  
  473.     if (initbatch == 0) {            /* online-mode only, please */
  474.         while (!keypressed()) ;     /* enable help */
  475.         kbdchar = getakey();
  476.         }
  477.     else
  478.         kbdchar = 27;
  479.     if (kbdchar == 32) continue;        /* spacebar stops scrolling */
  480.     while (kbdchar == 13 || kbdchar == 1013) { /* ENTER calls help, here */
  481.         kbdchar = help();
  482.         }
  483.     adapter = -1;                /* no video adapter yet */
  484.     for (k = 0; k < maxvideomode; k++)    /* search for an adapter */
  485.         if (kbdchar == kbdkeys[k])
  486.             adapter = k;        /* use this adapter */
  487.     if (adapter >= 0) break;        /* bail out if we found one */
  488.     if (kbdchar == 1082) goto restart;    /* restart pgm on Insert Key */
  489.     if (kbdchar == 1000) goodbye();     /* Control-C */
  490.     if (kbdchar == 27) goodbye();        /* exit to DOS on Escape Key */
  491.     if (kbdchar == 1083) goodbye();     /* exit to DOS on Delete Key */
  492.     if (kbdchar == 'd' || kbdchar == 'D') { /* shell to DOS */
  493.         clscr();
  494.         printf("\n\nShelling to DOS - type 'exit' to return\n\n");
  495.         shell_to_dos();
  496.         goto restart;
  497.         }
  498.     if (kbdchar == '1' || kbdchar == '2') { /* select single or dual-pass */
  499.         numpasses = kbdchar - '1';
  500.         solidguessing = boundarytraceflag = 0;
  501.         continue;
  502.         }
  503.     if (kbdchar == 'g' || kbdchar == 'G') { /* solid-guessing */
  504.         numpasses = 1;
  505.         boundarytraceflag = 0;
  506.         solidguessing = 1;
  507.         continue;
  508.         }
  509.     if (kbdchar == 'n' || kbdchar == 'N') { /* normal palette */
  510.         LogFlag = 0;
  511.         /* ChkLogFlag(); */
  512.         continue;
  513.         }
  514.     if (kbdchar == 'l' || kbdchar == 'L') { /* logarithmic palette */
  515.         LogFlag = 1;
  516.         continue;
  517.         }
  518.     if (kbdchar == 'r' || kbdchar == 'R' || kbdchar == '3'
  519.         || kbdchar == 'o' || kbdchar == 'O') {  /* restore old image    */
  520.         display3d = 0;
  521.         if (kbdchar == '3' || kbdchar == 'o' ||
  522.             kbdchar == 'O') display3d = 1;
  523.         setvideomode(3,0,0,0);    /* switch to text mode */
  524.             printf("\n Restart from what file? ");
  525.             gets(readname);
  526.             goto restorestart;
  527.             }
  528.     if (kbdchar == 't' || kbdchar == 'T') { /* set fractal type */
  529.         olddotmode = dotmode;    /* save the old dotmode */
  530.         dotmode = 1;        /* force a disable of any 8514/A */
  531.         if ((j = get_fracttype(initfractype)) < 0) goto restart;
  532.         dotmode = olddotmode;
  533.         goto restart;
  534.         }
  535.     if (kbdchar == 'x' || kbdchar == 'X') { /* generic toggle switch */
  536.         clscr();
  537.         get_toggles();            /* get the parameters */
  538.         goto restart;            /* restore the screen */
  539.         }
  540.     if (kbdchar == 'f' || kbdchar == 'F') { /* floating pt toggle */
  541.         if (floatflag == 0)
  542.             floatflag = 1;
  543.         else
  544.             floatflag = 0;
  545.         goto restart;
  546.         }
  547.     if (kbdchar == 'e' || kbdchar == 'E') { /* set IFS fractal parms */
  548.         clscr();
  549.         get_ifs_params();        /* get the parameters */
  550.         goto restart;
  551.         }
  552.     if (kbdchar == 'h' || kbdchar == 'H') { /* obsolete command-key */
  553.         clscr();
  554.         get_obsolete();         /* display obsolete msg */
  555.         goto restart;            /* restore the screen */
  556.         }
  557.     else
  558.         buzzer(2);
  559.     }
  560.  
  561. zoomoff = 1;                    /* zooming is enabled */
  562.  
  563. helpmode = HELPMAIN;                /* switch help modes */
  564.  
  565.  
  566. more = 1;
  567. while (more) {                    /* eternal loop */
  568.  
  569.     if (calc_status != 2 || (*readname && showfile==0)) {
  570.                         /* collect adapter info */
  571.         fromvideotable(adapter);
  572.         axmode    = videoentry.videomodeax; /* video mode (BIOS call) */
  573.         bxmode    = videoentry.videomodebx; /* video mode (BIOS call) */
  574.         cxmode    = videoentry.videomodecx; /* video mode (BIOS call) */
  575.         dxmode    = videoentry.videomodedx; /* video mode (BIOS call) */
  576.         dotmode = videoentry.dotmode;    /* assembler dot read/write */
  577.         xdots    = videoentry.xdots;    /* # dots across the screen */
  578.         ydots    = videoentry.ydots;    /* # dots down the screen   */
  579.         colors    = videoentry.colors;    /* # colors available */
  580.         if(debugflag==1984)
  581.         {  /* quick calc of small image */
  582.            xdots = xdots>>2;
  583.            ydots = ydots>>2;
  584.         }
  585.         dxsize = xdots - 1;        /* convert just once now */
  586.         dysize = ydots - 1;
  587.  
  588.         diskvideo = 0;            /* set diskvideo flag */
  589.         if (dotmode == 11)        /* default assumption is disk */
  590.             diskvideo = 2;
  591.  
  592.         memcpy(olddacbox,dacbox,256*3); /* save the DAC */
  593.         diskisactive = 1;        /* flag for disk-video routines */
  594.         if (overlay3d) {
  595.             setforgraphics();    /* restore old graphics image */
  596.             overlay3d = 0;
  597.             }
  598.         else
  599.             setvideomode(axmode,bxmode,cxmode,dxmode); /* switch video modes */
  600.         diskisactive = 0;        /* flag for disk-video routines */
  601.         if (savedac) {
  602.             memcpy(dacbox,olddacbox,256*3); /* restore the DAC */
  603.             if (dotmode != 11)
  604.                 spindac(0,1);
  605.             }
  606.         else if (dotmode == 11 && colors == 256) { /* disk video */
  607.             FILE *dacfile;
  608.             findpath("default.map",temp1);
  609.             dacfile = fopen(temp1,"r");
  610.             if (dacfile != NULL) {
  611.                 ValidateLuts(dacfile);    /* read the palette file */
  612.                 fclose(dacfile);
  613.                 }
  614.             }
  615.         }
  616.  
  617.     savedac = 1;                /* assume we save next time */
  618.  
  619.     if (initbatch == 0)
  620.         lookatmouse = -1073;        /* mouse left button == pgup */
  621.  
  622.     if(*readname && showfile==0) {
  623.         /*
  624.         only requirements for gifview: take file name in global
  625.         variable "readname" - link to frasmint's video (I used putcolor),
  626.         and should NOT set video mode (that's done here)
  627.         */
  628.  
  629.     if (display3d)            /* set up 3D decoding */
  630.        outln = line3d;
  631.     else if(filetype >= 1)
  632.        outln = outlin16;
  633.     else if(comparegif)
  634.        outln = cmp_line;
  635.     else
  636.        outln = out_line;
  637.  
  638.     if(filetype == 0)
  639.        status = funny_glasses_call(gifview);
  640.     else
  641.        status = funny_glasses_call(tgaview);
  642.     if(status==0)
  643.        buzzer(0);
  644.     else
  645.        calc_status = -1;
  646.     if(status == -1 && keypressed())
  647.            getakey();
  648.     /*    display3d = 0;               turn off 3D retrievals */
  649.         }
  650.  
  651.     integerfractal = fractalspecific[fractype].isinteger;
  652.  
  653.     zoomoff = 1;                /* zooming is enabled */
  654.     if (dotmode == 11 || (fractalspecific[fractype].flags&NOZOOM) != 0)
  655.         zoomoff = 0;    /* for these situations disable zooming */
  656.  
  657.     ccreal = param[0]; ccimag = param[1];
  658.  
  659.     adjust_to_limits(1.0); /* make sure all corners in valid range */
  660.  
  661.     delxx  = (xxmax - xx3rd) / dxsize; /* calculate stepsizes */
  662.     delyy  = (yymax - yy3rd) / dysize;
  663.     delxx2 = (xx3rd - xxmin) / dysize;
  664.     delyy2 = (yy3rd - yymin) / dxsize;
  665.  
  666.     creal = ccreal * fudge; /* integer equivs for it all */
  667.     cimag = ccimag * fudge;
  668.     xmin  = xxmin * fudge;
  669.     xmax  = xxmax * fudge;
  670.     x3rd  = xx3rd * fudge;
  671.     ymin  = yymin * fudge;
  672.     ymax  = yymax * fudge;
  673.     y3rd  = yy3rd * fudge;
  674.     delx  = delxx * fudge;
  675.     dely  = delyy * fudge;
  676.     delx2 = delxx2 * fudge;
  677.     dely2 = delyy2 * fudge;
  678.  
  679.     if (integerfractal && !invert)
  680.     {
  681.         if ( (delx  == 0 && delxx  != 0.0)
  682.           || (delx2 == 0 && delxx2 != 0.0)
  683.           || (dely  == 0 && delyy  != 0.0)
  684.           || (dely2 == 0 && delyy2 != 0.0) )
  685.             goto expand_retry;
  686.         lx0[0] = xmin;            /* fill up the x, y grids */
  687.         ly0[0] = ymax;
  688.         lx1[0] = ly1[0] = 0;
  689.         for (i = 1; i < xdots; i++ )
  690.         {
  691.             lx0[i] = lx0[i-1] + delx;
  692.             ly1[i] = ly1[i-1] - dely2;
  693.         }
  694.         for (i = 1; i < ydots; i++ )
  695.         {
  696.             ly0[i] = ly0[i-1] - dely;
  697.             lx1[i] = lx1[i-1] + delx2;
  698.         }
  699.         /* past max res?  check corners within 10% of expected */
  700.         if (  ratio_bad((double)lx0[xdots-1]-xmin,(double)xmax-x3rd)
  701.            || ratio_bad((double)ly0[ydots-1]-ymax,(double)y3rd-ymax)
  702.            || ratio_bad((double)lx1[(ydots>>1)-1],((double)x3rd-xmin)/2)
  703.            || ratio_bad((double)ly1[(xdots>>1)-1],((double)ymin-y3rd)/2) )
  704.         {
  705. expand_retry:        if (integerfractal &&    /* integer fractal type? */
  706.                 fractalspecific[fractype].tofloat != NOFRACTAL)
  707.                 floatflag = 1;    /* switch to floating pt */
  708.             else
  709.                 adjust_to_limits(2.0); /* double the size */
  710.             reset_initparms();
  711.             goto restart;
  712.         }
  713.         /* re-set corners to match reality */
  714.         xmax = lx0[xdots-1] + lx1[ydots-1];
  715.         ymin = ly0[ydots-1] + ly1[xdots-1];
  716.         x3rd = xmin + lx1[ydots-1];
  717.         y3rd = ly0[ydots-1];
  718.         xxmin = (double)xmin / fudge;
  719.         xxmax = (double)xmax / fudge;
  720.         xx3rd = (double)x3rd / fudge;
  721.         yymin = (double)ymin / fudge;
  722.         yymax = (double)ymax / fudge;
  723.         yy3rd = (double)y3rd / fudge;
  724.     }
  725.     else
  726.     {
  727.         /* set up dx0 and dy0 analogs of lx0 and ly0 */
  728.         /* put fractal parameters in doubles */
  729.         dx0[0] = xxmin;         /* fill up the x, y grids */
  730.         dy0[0] = yymax;
  731.         dx1[0] = dy1[0] = 0;
  732.         for (i = 1; i < xdots; i++ )
  733.         {
  734.             dx0[i] = dx0[i-1] + delxx;
  735.             dy1[i] = dy1[i-1] - delyy2;
  736.         }
  737.         for (i = 1; i < ydots; i++ )
  738.         {
  739.             dy0[i] = dy0[i-1] - delyy;
  740.             dx1[i] = dx1[i-1] + delxx2;
  741.         }
  742.         if (  ratio_bad(dx0[xdots-1]-xxmin,xxmax-xx3rd)
  743.            || ratio_bad(dy0[ydots-1]-yymax,yy3rd-yymax)
  744.            || ratio_bad(dx1[ydots-1],xx3rd-xxmin)
  745.            || ratio_bad(dy1[xdots-1],yymin-yy3rd))
  746.             goto expand_retry;
  747.         /* re-set corners to match reality */
  748.         xxmax = dx0[xdots-1] + dx1[ydots-1];
  749.         yymin = dy0[ydots-1] + dy1[xdots-1];
  750.         xx3rd = xxmin + dx1[ydots-1];
  751.         yy3rd = dy0[ydots-1];
  752.     }
  753.  
  754.     /* for periodicity close-enough, and for unity: */
  755.     /*     min(max(delx,delx2),max(dely,dely2)    */
  756.     ddelmin = fabs(delxx);
  757.     if (fabs(delxx2) > ddelmin)
  758.         ddelmin = fabs(delxx2);
  759.     if (fabs(delyy) > fabs(delyy2)) {
  760.         if (fabs(delyy) < ddelmin)
  761.             ddelmin = fabs(delyy);
  762.     }
  763.     else
  764.         if (fabs(delyy2) < ddelmin)
  765.             ddelmin = fabs(delyy2);
  766.     delmin = ddelmin * fudge;
  767.  
  768.     /* calculate factors which plot real values to screen co-ords */
  769.     /* calcfrac.c plot_orbit routines have comments about this    */
  770.     ftemp = (0.0-delyy2) * delxx2 * dxsize * dysize
  771.         - (xxmax-xx3rd) * (yy3rd-yymax);
  772.     plotmx1 = delxx2 * dxsize * dysize / ftemp;
  773.     plotmx2 = (yy3rd-yymax) * dxsize / ftemp;
  774.     plotmy1 = (0.0-delyy2) * dxsize * dysize / ftemp;
  775.     plotmy2 = (xxmax-xx3rd) * dysize / ftemp;
  776.  
  777.     sxmin = xxmin; /* save 3 corners for zoom.c ref points */
  778.     sxmax = xxmax;
  779.     sx3rd = xx3rd;
  780.     symin = yymin;
  781.     symax = yymax;
  782.     sy3rd = yy3rd;
  783.  
  784.      if ((fractype == MANDEL || fractype == JULIA) && bitshift == 29)
  785.         decomp[1] = 0;    /* make the world safe for decomposition */
  786.  
  787.     if (history[0].fractype == -1)        /* initialize the history file */
  788.         for (i = 0; i < MAXHISTORY; i++) {
  789.             history[i].xxmax = xxmax;
  790.             history[i].xxmin = xxmin;
  791.             history[i].yymax = yymax;
  792.             history[i].yymin = yymin;
  793.             history[i].xx3rd = xx3rd;
  794.             history[i].yy3rd = yy3rd;
  795.             history[i].param[0] = param[0];
  796.             history[i].param[1] = param[1];
  797.             history[i].fractype = fractype;
  798.         }
  799.  
  800.     if (history[historyptr].xxmax != xxmax    ||    /* save any (new) zoom data */
  801.         history[historyptr].xxmin != xxmin    ||
  802.         history[historyptr].yymax != yymax    ||
  803.         history[historyptr].yymin != yymin    ||
  804.         history[historyptr].xx3rd != xx3rd    ||
  805.         history[historyptr].yy3rd != yy3rd    ||
  806.         history[historyptr].param[0] != param[0] ||
  807.         history[historyptr].param[1] != param[1] ||
  808.         history[historyptr].fractype != fractype) {
  809.         if (++historyptr == MAXHISTORY) historyptr = 0;
  810.         history[historyptr].xxmax = xxmax;
  811.         history[historyptr].xxmin = xxmin;
  812.         history[historyptr].yymax = yymax;
  813.         history[historyptr].yymin = yymin;
  814.         history[historyptr].xx3rd = xx3rd;
  815.         history[historyptr].yy3rd = yy3rd;
  816.         history[historyptr].param[0] = param[0];
  817.         history[historyptr].param[1] = param[1];
  818.         history[historyptr].fractype = fractype;
  819.         }
  820.  
  821.     if(*readname && showfile==0) {
  822.         showfile = 1;
  823.         if (initbatch == 1 && calc_status == 2)
  824.             initbatch = -1; /* flag to finish calc before save */
  825.         }
  826.     else    {
  827.         diskisactive = 1;    /* flag for disk-video routines */
  828.     /* TW 07/21/89 - see below */
  829.     /* set save parameters in save structure */
  830.         setup_save_info();
  831.         if (initsavetime != 0        /* autosave and resumable? */
  832.             && (fractalspecific[fractype].flags&NORESUME) == 0) {
  833.             savebase = readticker(); /* calc's start time */
  834.             saveticks = initsavetime * 1092; /* bios ticks/minute */
  835.             if ((saveticks & 65535) == 0)
  836.                 ++saveticks;    /* make low word nonzero */
  837.             }
  838.  
  839.         if ((i = calcfract()) == 0)    /* draw the fractal using "C" */
  840.             buzzer(0);        /* finished!! */
  841.         saveticks = 0;            /* turn off autosave timer */
  842.         if( dotmode == 9 || dotmode == 11 ) {    /* if TARGA or disk-video */
  843.             if( dotmode == 11 )    /* TARGA already has some text up */
  844.                 home();
  845.             else
  846.                 EndTGA();    /* make sure TARGA is OFF */
  847.             if (i == 0)
  848.                 printf("Image has been completed");
  849.             }
  850.  
  851.         diskisactive = 0;    /* flag for disk-video routines */
  852.         }
  853.  
  854.     boxcount = 0;                /* no zoom box yet  */
  855.     zwidth = 0;
  856.  
  857.     if (fractype == PLASMA && cpu > 88) {
  858.         cyclelimit = 256;        /* plasma clouds need quick spins */
  859.         daccount = 256;
  860.         daclearn = 1;
  861.         }
  862.  
  863. resumeloop:                    /* return here on failed overlays */
  864.  
  865.     kbdmore = 1;
  866.     while (kbdmore == 1) {            /* loop through cursor keys */
  867.         if (timedsave != 0) {
  868.             if (timedsave == 1) {    /* woke up for timed save */
  869.                 getakey();    /* eat the dummy char */
  870.                 kbdchar = 's';  /* do the save */
  871.                 timedsave = 2;
  872.                 }
  873.             else {            /* save done, resume */
  874.                 timedsave = 0;
  875.                 resave_flag = 1;
  876.                 kbdchar = 13;
  877.                 }
  878.             }
  879.         else if (initbatch == 0) {    /* online only, please */
  880.             lookatmouse = (zwidth == 0) ? -1073 : 3;
  881.             while (!keypressed());    /* enables help */
  882.             kbdchar = getakey();
  883.             }
  884.         else {                /* batch mode special  */
  885.             if (initbatch == -1) {    /* finish calc */
  886.                 kbdchar = 13;
  887.                 initbatch = 1;
  888.                 }
  889.             else if (initbatch == 1) { /* save-to-disk     */
  890.                 if (debugflag == 50)
  891.                     kbdchar = 'r';
  892.                 else
  893.                     kbdchar = 's';
  894.                 initbatch = 2;
  895.                 }
  896.             else
  897.                 kbdchar = 27;    /* then, exit           */
  898.             }
  899.         switch (kbdchar) {
  900.             case 't':                       /* new fractal type */
  901.             case 'T':
  902.                 olddotmode = dotmode;    /* save the old dotmode */
  903.                 dotmode = 1;        /* force a disable of any 8514/A */
  904.                 if ((j = get_fracttype(fractype)) < 0) goto restart;
  905.                 savedac = 0;
  906.                 initmode = adapter;
  907.                 dotmode = olddotmode;
  908.                 frommandel = 0;
  909.                 goto restart;
  910.                 break;
  911.             case 'x':                       /* boundary tracing toggle */
  912.             case 'X':
  913.                 setfortext();        /* switch to text mode */
  914.                 i = get_toggles();    /* get the parameters */
  915.                 setforgraphics();    /* back to graphics */
  916.                 if (i > 0)        /* time to redraw? */
  917.                     kbdmore = calc_status = 0;
  918.                 if (i == 2) {        /* float change? */
  919.                     reset_initparms();
  920.                     goto restart;
  921.                     }
  922.                 break;
  923.             case 'f':                       /* floating pt toggle */
  924.             case 'F':
  925.                 if (floatflag == 0)
  926.                     floatflag = 1;
  927.                 else
  928.                     floatflag = 0;
  929.                 reset_initparms();
  930.                 goto restart;
  931.             case 'e':                       /* new IFS parms    */
  932.             case 'E':
  933.                 setfortext();        /* switch to text mode */
  934.                 get_ifs_params();    /* get the parameters */
  935.                 setforgraphics();    /* back to graphics */
  936.                 calc_status = kbdmore = 0;
  937.                 break;
  938.             case 'i':                       /* inversion parms    */
  939.             case 'I':
  940.                 setfortext();        /* switch to text mode */
  941.                 get_invert_params();    /* get the parameters */
  942.                 setforgraphics();    /* back to graphics */
  943.                 reset_initparms();
  944.                 invert = (inversion[0]==0.0) ? 0 : 3;
  945.                 goto restart;
  946.             case 'q':                       /* decomposition parms    */
  947.             case 'Q':
  948.                 setfortext();        /* switch to text mode */
  949.                 get_decomp_params();    /* get the parameters */
  950.                 setforgraphics();    /* back to graphics */
  951.                 kbdmore = calc_status = 0;
  952.                 break;
  953.             case 'a':                       /* starfield parms    */
  954.             case 'A':
  955.                 get_starfield_params(); /* get the parameters */
  956.                 calc_status = 0;
  957.                 continue;
  958.                 break;
  959.             case 32:            /* spacebar */
  960.                 if (fractalspecific[fractype].tojulia != NOFRACTAL
  961.                     && ccreal == 0.0 && ccimag == 0.0) {
  962.                    /* switch to corresponding Julia set */
  963.                    fractype = fractalspecific[fractype].tojulia;
  964.                    ccreal = (xxmax + xxmin) / 2;
  965.                    ccimag = (yymax + yymin) / 2;
  966.                    param[0] = ccreal;
  967.                    param[1] = ccimag;
  968.  
  969.                    jxxmin = sxmin; jxxmax = sxmax;
  970.                    jyymax = symax; jyymin = symin;
  971.                    jxx3rd = sx3rd; jyy3rd = sy3rd;
  972.                    frommandel = 1;
  973.  
  974.                    xxmin = fractalspecific[fractype].xmin;
  975.                    xxmax = fractalspecific[fractype].xmax;
  976.                    yymin = fractalspecific[fractype].ymin;
  977.                    yymax = fractalspecific[fractype].ymax;
  978.                    xx3rd = xxmin;
  979.                    yy3rd = yymin;
  980.  
  981.                    if(biomorph != -1 && bitshift != 29) {
  982.                       xxmin *= 3.0;
  983.                       xxmax *= 3.0;
  984.                       yymin *= 3.0;
  985.                       yymax *= 3.0;
  986.                       xx3rd *= 3.0;
  987.                       yy3rd *= 3.0;
  988.                       }
  989.  
  990.                    zoomoff = 1;
  991.                    calc_status = 0;
  992.                    kbdmore = 0;
  993.                    }
  994.  
  995.                 else if (fractalspecific[fractype].tomandel != NOFRACTAL) {
  996.                    /* switch to corresponding Mandel set */
  997.                    fractype = fractalspecific[fractype].tomandel;
  998.                    if (frommandel) {
  999.                       xxmin = jxxmin;  xxmax = jxxmax;
  1000.                       yymin = jyymin;  yymax = jyymax;
  1001.                       xx3rd = jxx3rd;  yy3rd = jyy3rd;
  1002.                       }
  1003.                    else {
  1004.                       ccreal = (fractalspecific[fractype].xmax - fractalspecific[fractype].xmin) / 2;
  1005.                       ccimag = (fractalspecific[fractype].ymax - fractalspecific[fractype].ymin) / 2;
  1006.                       xxmin = xx3rd = param[0] - ccreal;
  1007.                       xxmax = param[0] + ccreal;
  1008.                       yymin = yy3rd = param[1] - ccimag;
  1009.                       yymax = param[1] + ccimag;
  1010.                       }
  1011.                    ccreal = 0;
  1012.                    ccimag = 0;
  1013.                    param[0] = 0;
  1014.                    param[1] = 0;
  1015.                    zoomoff = 1;
  1016.                    calc_status = 0;
  1017.                    kbdmore = 0;
  1018.                    }
  1019.  
  1020.                 else buzzer(2);     /* no switch */
  1021.                 break;
  1022.             case 1071:            /* home */
  1023.                 if (--historyptr < 0)
  1024.                     historyptr = MAXHISTORY-1;
  1025.                 xxmax  = history[historyptr].xxmax;
  1026.                 xxmin  = history[historyptr].xxmin;
  1027.                 yymax  = history[historyptr].yymax;
  1028.                 yymin  = history[historyptr].yymin;
  1029.                 xx3rd  = history[historyptr].xx3rd;
  1030.                 yy3rd  = history[historyptr].yy3rd;
  1031.                 param[0] = history[historyptr].param[0];
  1032.                 param[1] = history[historyptr].param[1];
  1033.                 fractype = history[historyptr].fractype;
  1034.                 ccreal = param[0]; ccimag = param[1];
  1035.                 zoomoff = 1;
  1036.                 reset_initparms();
  1037.                 if (fractalspecific[fractype].isinteger != 0 &&
  1038.                     fractalspecific[fractype].tofloat != NOFRACTAL)
  1039.                     floatflag = 0;
  1040.                 if (fractalspecific[fractype].isinteger == 0 &&
  1041.                     fractalspecific[fractype].tofloat != NOFRACTAL)
  1042.                     floatflag = 1;
  1043.                 goto restart;
  1044.             case 'd':                       /* shell to MS-DOS */
  1045.             case 'D':
  1046.                 setfortext();
  1047.                 printf("\n\nShelling to DOS - type 'exit' to return\n\n");
  1048.                 if (axmode == 0 || axmode > 7) {
  1049. static char far dosmsg[]={"\
  1050. Note:  Your graphics image is still squirreled away in your video\n\
  1051. adapter's memory.  Switching video modes (say, to get your cursor back)\n\
  1052. will clobber part of that image.  Sorry - it's the best we could do.\n\n"};
  1053.                     helpmessage(dosmsg);
  1054.                     }
  1055.                 shell_to_dos();
  1056.                 setforgraphics();
  1057.                 calc_status = 0;
  1058.                 break;
  1059.             case '<':                       /* lower iter maximum */
  1060.             case ',':
  1061.                 if (maxit >= 10+initincr) maxit -= initincr;
  1062.                 maxit -= initincr;    /* for fall-thru */
  1063.             case '>':                       /* raise iter maximum */
  1064.             case '.':
  1065.                 if (maxit <= 32000-initincr) maxit += initincr;
  1066.                 calc_status = 0;
  1067.                 continue;
  1068.             case 'c':                       /* switch to cycling */
  1069.             case 'C':
  1070.                 rotate(0);
  1071.                 continue;
  1072.             case '+':                       /* rotate palette */
  1073.                 rotate(+1);
  1074.                 continue;
  1075.             case '-':                       /* rotate palette */
  1076.                 rotate(-1);
  1077.                 continue;
  1078.             case 's':                       /* save-to-disk */
  1079.             case 'S':
  1080.                 saveanimage();
  1081.                 resave_flag = 0;
  1082.                 continue;
  1083.             case 'o':                       /* 3D overlay */
  1084.             case 'O':
  1085.                 overlay3d = 1;
  1086.             case '3':                       /* restore-from (3d) */
  1087.                 display3d = 1;
  1088.             case 'r':                       /* restore-from */
  1089.             case 'R':
  1090.                 comparegif = 0;
  1091.                 frommandel = 0;
  1092.                 if(kbdchar == 'r' || kbdchar == 'R')
  1093.                 {
  1094.                    if(debugflag == 50)
  1095.                    {
  1096.                       comparegif = overlay3d = 1;
  1097.                       if (initbatch == 2)
  1098.                       {
  1099.                      setfortext();     /* save graphics image */
  1100.                      strcpy(readname,savename);
  1101.                      goto restorestart;
  1102.                       }
  1103.                    }
  1104.                    else
  1105.                       comparegif = overlay3d = 0;
  1106.                    display3d = 0;
  1107.                 }
  1108.                 olddotmode = dotmode;    /* save the old dotmode */
  1109.                 if (overlay3d) {
  1110.                     setfortext();    /* save graphics image */
  1111.                     printf("\n Overlay from");
  1112.                     }
  1113.                 else    {
  1114.                     dotmode = 1;        /* in case of an 8514/A mode */
  1115.                     setvideomode(3,0,0,0);    /* switch to text mode */
  1116.                     printf("\n Restart from");
  1117.                     }
  1118.                 if (*readname)
  1119.                     printf(" what file (if not %s)? ",
  1120.                         readname);
  1121.                 else
  1122.                     printf(" what file? ");
  1123.                 temp1[0] = 0;
  1124.                 gets(temp1);
  1125.                 if (temp1[0] != 0)
  1126.                     strcpy(readname,temp1);
  1127.                 dotmode = olddotmode;
  1128.                 resave_flag = 0;
  1129.                 goto restorestart;
  1130.                 break;
  1131.             case '1':                       /* single-pass mode */
  1132.             case '2':                       /* dual-pass mode */
  1133.                 numpasses = kbdchar - '1';
  1134.                 solidguessing = boundarytraceflag = 0;
  1135.                 kbdmore = calc_status = 0;
  1136.                 break;
  1137.             case 'g':                       /* solid-guessing */
  1138.             case 'G':
  1139.                 numpasses = 1;
  1140.                 solidguessing = 1;
  1141.                 boundarytraceflag = 0;
  1142.                 kbdmore = calc_status = 0;
  1143.                 break;
  1144.             case 'n':                       /* normal palette */
  1145.             case 'N':
  1146.                 LogFlag = 0;
  1147.                 kbdmore = calc_status = 0;
  1148.                 break;
  1149.             case 'l':                       /* log palette */
  1150.             case 'L':
  1151.                 LogFlag = 1;
  1152.                 kbdmore = calc_status = 0;
  1153.                 break;
  1154.             case 'b':                       /* make batch file */
  1155.             case 'B':
  1156.                 make_batch_file();
  1157.                 break;
  1158.             case 'p':
  1159.             case 'P':
  1160.                 Print_Screen();
  1161.                 if (!keypressed()) buzzer(0);
  1162.                  else {
  1163.                     buzzer(1);
  1164.                     getakey();
  1165.                  }
  1166.                 continue;
  1167.                 /*  ^^^^^  MDS 7/1/89  ^^^^^  */
  1168.             case 13:            /* Enter */
  1169.             case 1013:            /* Numeric-Keypad Enter */
  1170.             case 1079:            /* end */
  1171.                 init_pan_or_recalc(0);
  1172.                 kbdmore = 0;
  1173.                 break;
  1174.             case 10:            /* control-Enter */
  1175.             case 1010:            /* Control-Keypad Enter */
  1176.                 init_pan_or_recalc(1);
  1177.                 kbdmore = 0;
  1178.                 zoomout(); /* calc corners for zooming out */
  1179.                 break;
  1180.             case 1082:            /* insert */
  1181.                 dotmode = 1;
  1182.                 setvideomode(3,0,0,0);    /* force text mode */
  1183.                 goto restart;
  1184.                 break;
  1185.             case 1000:            /* Control-C */
  1186.             case 27:            /* Escape */
  1187.             case 1083:            /* delete */
  1188.                 more = 0; kbdmore = 0;
  1189.                 break;
  1190.             case 1075:            /* cursor left */
  1191.             case 1077:            /* cursor right */
  1192.             case 1072:            /* cursor up */
  1193.             case 1080:            /* cursor down */
  1194.             case 1115:            /* Ctrl-cursor left */
  1195.             case 1116:            /* Ctrl-cursor right */
  1196.             case 1141:            /* Ctrl-cursor up */
  1197.             case 1145:            /* Ctrl-cursor down */
  1198.                 move_zoombox(kbdchar);
  1199.                 break;
  1200.             case 1119:            /* Ctrl-home */
  1201.                 if (boxcount && (fractalspecific[fractype].flags&NOROTATE) == 0) {
  1202.                     i = key_count(1119);
  1203.                     if ((zskew -= 0.02*i) < -0.48)
  1204.                         zskew = -0.48;
  1205.                 }
  1206.                 break;
  1207.             case 1117:            /* Ctrl-end */
  1208.                 if (boxcount && (fractalspecific[fractype].flags&NOROTATE) == 0) {
  1209.                     i = key_count(1117);
  1210.                     if ((zskew += 0.02*i) > 0.48)
  1211.                         zskew = 0.48;
  1212.                 }
  1213.                 break;
  1214.             case 1132:            /* Ctrl-pgup */
  1215.                 if (boxcount)
  1216.                     chgboxi(0,-2*key_count(1132));
  1217.                 break;
  1218.             case 1118:            /* Ctrl-pgdn */
  1219.                 if (boxcount)
  1220.                     chgboxi(0,2*key_count(1118));
  1221.                 break;
  1222.             case 1073:            /* page up */
  1223.                 if (zoomoff == 1)
  1224.                     if (zwidth == 0) { /* start zoombox */
  1225.                         zwidth = 1;
  1226.                         if ((boxcolor=colors-1) > 15)
  1227.                             boxcolor = 15; /* white? */
  1228.                         zdepth = 0.75;
  1229.                         zrotate = zskew = 0;
  1230.                         zbx = zby = 0;
  1231.                     }
  1232.                     else {
  1233.                         i = key_count(1073);
  1234.                         chgboxf(-0.036*i,-0.027*i);
  1235.                     }
  1236.                 break;
  1237.             case 1081:            /* page down */
  1238.                 if (boxcount) {
  1239.                     if (zwidth >= 1) /* end zoombox */
  1240.                         zwidth = 0;
  1241.                     else {
  1242.                         i = key_count(1081);
  1243.                         chgboxf(0.036*i,0.027*i);
  1244.                     }
  1245.                 }
  1246.                 break;
  1247.             case 1142:            /* Ctrl-kpad- */
  1248.                 if (boxcount && (fractalspecific[fractype].flags&NOROTATE) == 0)
  1249.                     zrotate += key_count(1142);
  1250.                 break;
  1251.             case 1144:            /* Ctrl-kpad+ */
  1252.                 if (boxcount && (fractalspecific[fractype].flags&NOROTATE) == 0)
  1253.                     zrotate -= key_count(1144);
  1254.                 break;
  1255.             case 1146:            /* Ctrl-ins */
  1256.                 boxcolor += key_count(1146);
  1257.                 break;
  1258.             case 1147:            /* Ctrl-del */
  1259.                 boxcolor -= key_count(1147);
  1260.                 break;
  1261.             case 'h':                       /* obsolete command key */
  1262.             case 'H':
  1263.                 setfortext();        /* switch to text mode */
  1264.                 get_obsolete();     /* inform user */
  1265.                 setforgraphics();    /* back to graphics */
  1266.                 break;
  1267.             default:        /* other (maybe a valid Fn key) */
  1268.                 for (k = 0; k < maxvideomode; k++)
  1269.                     if (kbdchar == kbdkeys[k]) {
  1270.                         adapter = k;
  1271.                         kbdmore = 0;
  1272.                         fromvideotable(adapter);
  1273.                         if (videoentry.dotmode != 11
  1274.                           || videoentry.colors != colors)
  1275.                             savedac = 0;
  1276.                         calc_status = 0;
  1277.                         }
  1278.                 if (kbdmore != 0)
  1279.                     continue;
  1280.                 break;
  1281.             }
  1282.  
  1283.         if (zoomoff == 1 && kbdmore == 1) /* draw/clear a zoom box? */
  1284.             drawbox(1);
  1285.         }
  1286.     }
  1287.     dotmode = 0;        /* no need to reinit TARGA 2 April 89 j mclain */
  1288.     goodbye();                /* we done. */
  1289.  
  1290. }
  1291.  
  1292. read_overlay()                /* read overlay/3D files, if reqr'd */
  1293. {
  1294. int kbdchar;
  1295. char accessmethod[2];            /* "B" if through the BIOS */
  1296.  
  1297. if(*readname){    /* This is why readname initialized to null string */
  1298.     if (!overlay3d)         /* overlays use the existing mode */
  1299.         initmode = -1;        /* no viewing mode set yet */
  1300.     else
  1301.         initmode = adapter;    /* use previous adapter mode for overlays */
  1302.     if(find_fractal_info(readname,&read_info)==0){
  1303.         inititer   = read_info.iterations;
  1304.         initfractype  = read_info.fractal_type;
  1305.         initxmin   = read_info.xmin;
  1306.         initxmax   = read_info.xmax;
  1307.         initymin   = read_info.ymin;
  1308.         initymax   = read_info.ymax;
  1309.         initparam[0]   = read_info.creal;
  1310.         initparam[1]   = read_info.cimag;
  1311.  
  1312.         if(read_info.version > 0)
  1313.         {
  1314.             initparam[2]  = read_info.parm3;
  1315.             initparam[3]  = read_info.parm4;
  1316.         potparam[0]   = read_info.potential[0];
  1317.         potparam[1]   = read_info.potential[1];
  1318.         potparam[2]   = read_info.potential[2];
  1319.         rflag          = read_info.rflag;
  1320.         rseed          = read_info.rseed;
  1321.         inside          = read_info.inside;
  1322.         LogFlag       = read_info.logmap;
  1323.         inversion[0]  = read_info.invert[0];
  1324.         inversion[1]  = read_info.invert[1];
  1325.         inversion[2]  = read_info.invert[2];
  1326.         decomp[0]     = read_info.decomp[0];
  1327.         decomp[1]     = read_info.decomp[1];
  1328.         biomorph      = read_info.biomorph;
  1329.         forcesymmetry = read_info.symmetry;
  1330.         }
  1331.  
  1332.         if(read_info.version > 1 && !display3d)
  1333.         {
  1334.                int i;
  1335.                for (i = 0; i < 16; i++)
  1336.                   init3d[i] = read_info.init3d[i];
  1337.            previewfactor   = read_info.previewfactor;
  1338.            xtrans       = read_info.xtrans;
  1339.            ytrans       = read_info.ytrans;
  1340.            red_crop_left   = read_info.red_crop_left;
  1341.            red_crop_right  = read_info.red_crop_right;
  1342.            blue_crop_left  = read_info.blue_crop_left;
  1343.            blue_crop_right = read_info.blue_crop_right;
  1344.            red_bright       = read_info.red_bright;
  1345.            blue_bright       = read_info.blue_bright;
  1346.            xadjust       = read_info.xadjust;
  1347.            eyeseparation   = read_info.eyeseparation;
  1348.            glassestype       = read_info.glassestype;
  1349.         }
  1350.  
  1351.         if(read_info.version > 2) {
  1352.            outside       = read_info.outside;
  1353.         }
  1354.  
  1355.         calc_status = 0;      /* defaults if version < 4 */
  1356.         initx3rd = initxmin;
  1357.         inity3rd = initymin;
  1358.         distest = 0;
  1359.         calctime = 0;
  1360.         if(read_info.version > 3)
  1361.         {
  1362.            initx3rd = read_info.x3rd;
  1363.            inity3rd = read_info.y3rd;
  1364.            calc_status = read_info.calc_status;
  1365.            boundarytraceflag = initsolidguessing = 0;
  1366.            initpass = 2;
  1367.            switch (read_info.stdcalcmode) {
  1368.               case '1': initpass = 1;
  1369.                 break;
  1370.               case '2': initpass = 2;
  1371.                 break;
  1372.               case 'b': boundarytraceflag = 1;
  1373.                 break;
  1374.               default:    initsolidguessing = 1;
  1375.               }
  1376.            distest = read_info.distest;
  1377.            floatflag = read_info.floatflag;
  1378.            bailout = read_info.bailout;
  1379.            calctime = read_info.calctime;
  1380.            trigndx[0] = read_info.trigndx[0];
  1381.            trigndx[1] = read_info.trigndx[1];
  1382.            trigndx[2] = read_info.trigndx[2];
  1383.            trigndx[3] = read_info.trigndx[3];
  1384.            finattract = read_info.finattract;
  1385.        initorbit.x    = read_info.initorbit[0];
  1386.        initorbit.y    = read_info.initorbit[1];
  1387.        useinitorbit = read_info.useinitorbit;
  1388.            periodicitycheck = read_info.periodicity;
  1389.         }
  1390.         if(read_info.version < 4) {
  1391.            backwardscompat(); /* translate obsolete types */
  1392.            if (LogFlag)
  1393.               LogFlag = 2;
  1394.            floatflag = (fractalspecific[initfractype].isinteger) ? 0 : 1;
  1395.            }
  1396.         fractalspecific[initfractype].paramvalue[0] = initparam[0];
  1397.         fractalspecific[initfractype].paramvalue[1] = initparam[1];
  1398.         fractalspecific[initfractype].paramvalue[2] = initparam[2];
  1399.         fractalspecific[initfractype].paramvalue[3] = initparam[3];
  1400.         set_trig_pointers(-1);
  1401.  
  1402.         showfile = 0;
  1403.     if (!overlay3d) {        /* don't worry about the video if overlay */
  1404.         if ((hasconfig || askvideo) && read_info.info_id[0] == 'G') {
  1405. static char far unknownmsg[]={"\
  1406. You have selected an unknown (non-fractal) GIF image\n\
  1407. I am treating this image as a PLASMA CLOUD of unknown video type\n"};
  1408.             buzzer(2);
  1409.             helpmessage(unknownmsg);
  1410.             }
  1411.         if (read_info.dotmode == 11 && ! initbatch) {
  1412. static char far novidmsg[]={"\
  1413. You have selected a fractal image generated in 'no-video' mode\n"};
  1414.             buzzer(2);
  1415.             helpmessage(novidmsg);
  1416.             }
  1417.         if ((hasconfig || askvideo) && read_info.info_id[0] == 'G')
  1418.             printf("with resolution %d x %d x %d\n",
  1419.                 read_info.xdots, read_info.ydots, read_info.colors);
  1420.         else
  1421.             initmode = getGIFmode(&read_info);
  1422.         if (initmode >= maxvideomode) initmode = -1;
  1423.         if (initmode >= 0 && (hasconfig || askvideo) && ! initbatch ){
  1424.             char c;
  1425.             fromvideotable(initmode);
  1426.             strcpy(accessmethod," ");
  1427.             if (videoentry.dotmode == 1)
  1428.                 accessmethod[0] = 'B';
  1429.             printf("fractal file contains following mode:\n\n");
  1430. #ifdef __TURBOC__
  1431.             printf("%-6.6s %-25.25s%5d x%4d%5d %1.1s  %-25.25s\n",
  1432. #else
  1433.             printf("%-6s %-25s%5d x%4d%5d %1s  %-25s\n",
  1434. #endif
  1435.                 fkeys[initmode],
  1436.                 videoentry.name,
  1437.                 videoentry.xdots,
  1438.                 videoentry.ydots,
  1439.                 videoentry.colors,
  1440.                 accessmethod,
  1441.                 videoentry.comment);
  1442.             if (videoentry.dotmode == 11)
  1443.                 printf("Restore in same disk video mode? ([Y] or N) --> ");
  1444.             else
  1445.                 printf("Legal for this machine? ([Y] or N) --> ");
  1446.             while((c=getch())!='y' && c!='Y' && c!='n' && c!='N' && c!=13);
  1447.             if( c == 'n' || c == 'N')
  1448.                 initmode = -1;
  1449.             }
  1450.         else    {
  1451.             /* initmode bad */
  1452.             if (initmode == -1 && initbatch)
  1453.                 showfile = 1; /* pretend already displayed */
  1454.             }
  1455.         if (initmode == -1)
  1456.             calc_status = 0;
  1457.         if (initmode == -1 && ! initbatch) {
  1458. static char far selmodemsg[]={"\
  1459. \nPlease select a video mode with which to view or recreate this\n\
  1460. image by pressing the appropriate function key (or press the ENTER)\n\
  1461. key to bail out without displaying this image).  You can also press\n\
  1462. the F1 or '?' keys to get help on the available video modes)\n"};
  1463.             helpmessage(selmodemsg);
  1464.             helpmode = HELPVIDEO;
  1465.             while (!keypressed());
  1466.             kbdchar = getakey();
  1467.             for (initmode = 0; initmode < maxvideomode; initmode++)
  1468.                 if (kbdchar == kbdkeys[initmode]) break;
  1469.             if (initmode == maxvideomode) {
  1470.                 *readname = 0; /* failed ... zap filename */
  1471.                 initmode = -1;
  1472.                 showfile = 1; /* pretend already displayed */
  1473.                 }
  1474.         }
  1475.             if (initmode >= 0) fromvideotable(initmode);
  1476.             if (initmode >= 0 && display3d == 0 && (
  1477.                 read_info.xdots != videoentry.xdots ||
  1478.                 read_info.ydots != videoentry.ydots)) {
  1479.                     *readname = 0; /* force regen */
  1480.                     return(0);
  1481.                     }
  1482.                 }
  1483.  
  1484.         if (initmode >= 0 && display3d) {
  1485.             calc_status = 0;
  1486.             initfractype = PLASMA;
  1487.             initparam[0] = 0;
  1488.             }
  1489.         if (get_3d_params() < 0) {
  1490.             initmode = -1;
  1491.             *readname = 0;
  1492.             return(0);
  1493.             }
  1494.         initcorners = 1;
  1495.         }
  1496.     else    {
  1497.         buzzer(2);
  1498.         initmode = -1;
  1499.         *readname = 0;
  1500.         }
  1501.     }
  1502. }
  1503.  
  1504. make_batch_file()
  1505. {
  1506.    double Xctr, Yctr, Magnification;
  1507.    FILE *batch;
  1508.    int numfn;
  1509.    batch = fopen("frabatch.bat", "a");
  1510.    if(batch == NULL)
  1511.       return(-1);
  1512.    fprintf(batch, "fractint");
  1513.  
  1514.    /********************************/
  1515.    /* universal parameters go here */
  1516.    /********************************/
  1517.    if(askvideo==0)
  1518.       fprintf(batch, " askvideo=no");
  1519.    if (warn)
  1520.       fprintf(batch, " warn=yes");
  1521.    if (mapset && *MAP_name)
  1522.    {
  1523.       /* strip path from file name */
  1524.       char *p;
  1525.       p = strrchr(MAP_name,'\\');
  1526.       if(p)
  1527.      fprintf(batch, " map=%s", p+1);
  1528.       else
  1529.      fprintf(batch, " map=%s", MAP_name);
  1530.    }
  1531.    if (inside == -1)
  1532.       fprintf(batch, " inside=maxiter");
  1533.    else if (inside == -60)
  1534.       fprintf(batch, " inside=bof60");
  1535.    else if (inside == -61)
  1536.       fprintf(batch, " inside=bof61");
  1537.    else if (inside != 1)
  1538.       fprintf(batch, " inside=%d", inside);
  1539.    if (finattract)
  1540.       fprintf(batch, " finattract=yes");
  1541.    if (outside != -1)
  1542.       fprintf(batch, " outside=%d", outside);
  1543.    if(forcesymmetry==XAXIS)
  1544.       fprintf(batch, " symmetry=xaxis");
  1545.    else if(forcesymmetry==YAXIS)
  1546.       fprintf(batch, " symmetry=yaxis");
  1547.    else if(forcesymmetry==XYAXIS)
  1548.       fprintf(batch, " symmetry=xyaxis");
  1549.    else if(forcesymmetry==ORIGIN)
  1550.       fprintf(batch, " symmetry=origin");
  1551.    else if(forcesymmetry==PI_SYM)
  1552.       fprintf(batch, " symmetry=pi");
  1553.    else if(forcesymmetry==NOSYM)
  1554.       fprintf(batch, " symmetry=none");
  1555.    if(LogFlag)
  1556.       fprintf(batch, (LogFlag == 1) ? " logmap=yes" : " logmap=old");
  1557.    if(rflag)
  1558.       fprintf(batch, " rseed=%d",rseed);
  1559.  
  1560.    showtrig(batch); /* this function is in prompts.c */
  1561.  
  1562.    /***********************************/
  1563.    /* fractal only parameters go here */
  1564.    /***********************************/
  1565.    if (display3d <= 0)    /* a fractal was generated */
  1566.    {
  1567.       if(periodicitycheck != 1)
  1568.          fprintf(batch, " periodicity=%d",periodicitycheck);
  1569.  
  1570.       if(potparam[0])
  1571.       {
  1572.      fprintf(batch, " potential=%d/%d/%d",
  1573.          (int)potparam[0],(int)potparam[1],(int)potparam[2]);
  1574.      if(potfile[0])
  1575.         fprintf(batch, "/%s", potfile);
  1576.       }
  1577.       if (fractalspecific[fractype].name[0] != '*')
  1578.      fprintf(batch, " type=%s", fractalspecific[fractype].name);
  1579.       else
  1580.      fprintf(batch, " type=%s", &fractalspecific[fractype].name[1]);
  1581.       if(usemag && cvtcentermag(&Xctr, &Yctr, &Magnification))
  1582.       {
  1583.      if (delmin > 1000)
  1584.         fprintf(batch, " center-mag=%g/%g/%g",
  1585.         Xctr,Yctr,Magnification);
  1586.      else
  1587.         fprintf(batch, " center-mag=%+20.17lf/%+20.17lf/%+20.17lf",
  1588.         Xctr,Yctr,Magnification);
  1589.       }
  1590.       else
  1591.       {
  1592.      if (delmin > 1000) {
  1593.         fprintf(batch, " corners=%g/%g/%g/%g",
  1594.         xxmin, xxmax, yymin, yymax);
  1595.         if (xx3rd != xxmin || yy3rd != yymin)
  1596.            fprintf(batch, "/%g/%g", xx3rd, yy3rd);
  1597.      }
  1598.      else {
  1599.         fprintf(batch, " corners=%+20.17lf/%+20.17lf/%+20.17lf/%+20.17lf",
  1600.         xxmin, xxmax, yymin, yymax);
  1601.         if (xx3rd != xxmin || yy3rd != yymin)
  1602.            fprintf(batch, "/%+20.17lf/%+20.17lf", xx3rd, yy3rd);
  1603.      }
  1604.       }
  1605.  
  1606.       if(param[0]!=0.0 || param[1]!=0.0 || param[2]!=0.0 || param[3]!=0.0)
  1607.      fprintf(batch, " params=%g/%g/%g/%g",
  1608.          param[0], param[1], param[2], param[3]);
  1609.       if (maxit != 150)
  1610.      fprintf(batch, " maxiter=%d", maxit);
  1611.       if (initincr != 50)
  1612.      fprintf(batch, " iterincr=%d", initincr);
  1613.       if (invert)
  1614.      fprintf(batch, " invert=%g/%g/%g",
  1615.          inversion[0], inversion[1], inversion[2]);
  1616.       if (decomp[0])
  1617.      fprintf(batch, " decomp=%d/%d", decomp[0], decomp[1]);
  1618.       if (distest)
  1619.      fprintf(batch, " distest=%d", distest);
  1620.       if (floatflag)
  1621.      fprintf(batch, " float=yes");
  1622.       if (biomorph != -1)
  1623.      fprintf(batch, " biomorph=%d", biomorph);
  1624.       if(bailout && fabs(potparam[2]) == 0.0 &&
  1625.         (decomp[0] <= 0 || decomp[1] <= 0))
  1626.      fprintf(batch, " bailout=%d",bailout);
  1627.       if (fractype == FORMULA || fractype == FFORMULA)
  1628.       {
  1629.      fprintf(batch, " formulafile=%s",FormFileName);
  1630.      fprintf(batch, " formulaname=%s",FormName);
  1631.       }
  1632.       if(useinitorbit == 2)
  1633.      fprintf(batch, " initorbit=pixel");
  1634.       else if(useinitorbit == 1)
  1635.      fprintf(batch, " initorbit=%g/%g",initorbit.x,initorbit.y);
  1636.    }
  1637.  
  1638.    /**********************************/
  1639.    /* line3d only parameters go here */
  1640.    /**********************************/
  1641.    if (display3d >= 1)    /* only for line3d */
  1642.    {
  1643.       fprintf(batch, " 3d=yes");
  1644.       if (showfile && *readname)
  1645.      fprintf(batch, " filename=%s", readname);
  1646.       if (SPHERE)
  1647.       {
  1648.      fprintf(batch, " sphere=yes");
  1649.      fprintf(batch, " latitude=%d/%d", THETA1, THETA2);
  1650.      fprintf(batch, " longitude=%d/%d", PHI1, PHI2);
  1651.      fprintf(batch, " radius=%d", RADIUS);
  1652.       }
  1653.       if (FILLTYPE)
  1654.      fprintf(batch, " filltype=%d",
  1655.          FILLTYPE);
  1656.       if (transparent[0] || transparent[1])
  1657.      fprintf(batch, " transparent=%d/%d",
  1658.          transparent[0],transparent[1]);
  1659.       if (preview)
  1660.       {
  1661.      fprintf(batch, " preview=yes");
  1662.      if (showbox)
  1663.         fprintf(batch, " showbox=yes");
  1664.      fprintf(batch, " coarse=%d",previewfactor);
  1665.       }
  1666.  
  1667.       if (RANDOMIZE)
  1668.      fprintf(batch, " randomize=%d",RANDOMIZE);
  1669.       if (full_color)
  1670.      fprintf(batch, " fullcolor=yes");
  1671.       if (Ambient)
  1672.      fprintf(batch, " ambient=%d",Ambient);
  1673.       if (haze)
  1674.      fprintf(batch, " haze=%d",haze);
  1675.       if (full_color)
  1676.       {
  1677.      /* strip path from file name */
  1678.      char *p;
  1679.      p = strrchr(Light_Name,'\\');
  1680.      if(p)
  1681.         fprintf(batch, " lightname=%s", p+1);
  1682.      else
  1683.         fprintf(batch, " lightname=%s", Light_Name);
  1684.       }
  1685.    }
  1686.  
  1687.    /***********************************/
  1688.    /* universal 3d parameters go here */
  1689.    /***********************************/
  1690.    if (display3d)        /* universal 3d */
  1691.    {
  1692.       if(!SPHERE)
  1693.       {
  1694.      fprintf(batch, " rotation=%d/%d/%d", XROT, YROT, ZROT);
  1695.      fprintf(batch, " scalexyz=%d/%d", XSCALE, YSCALE);
  1696.       }
  1697.       fprintf(batch, " roughness=%d", ROUGH);
  1698.       fprintf(batch, " waterline=%d", WATERLINE);
  1699.       fprintf(batch, " perspective=%d", ZVIEWER);
  1700.       fprintf(batch, " xyshift=%d/%d", XSHIFT, YSHIFT);
  1701.       if (FILLTYPE > 4)
  1702.      fprintf(batch, " lightsource=%d/%d/%d",
  1703.          XLIGHT, YLIGHT, ZLIGHT);
  1704.       if (LIGHTAVG && FILLTYPE > 4)
  1705.      fprintf(batch, " smoothing=%d", LIGHTAVG);
  1706.       if(xtrans || ytrans)
  1707.      fprintf(batch, " xyadjust=%d/%d",xtrans,ytrans);
  1708.       if(glassestype)
  1709.       {
  1710.      fprintf(batch, " stereo=%d",glassestype);
  1711.      fprintf(batch, " interocular=%d",eyeseparation);
  1712.      fprintf(batch, " converge=%d",xadjust);
  1713.      fprintf(batch, " crop=%d/%d/%d/%d",
  1714.          red_crop_left,red_crop_right,blue_crop_left,blue_crop_right);
  1715.      fprintf(batch, " bright=%d/%d",
  1716.          red_bright,blue_bright);
  1717.       }
  1718.    }
  1719.  
  1720.    fprintf(batch, "\n");
  1721.    if (batch != NULL)
  1722.       fclose(batch);
  1723.    return(0);
  1724. }
  1725.  
  1726. int shell_to_dos()
  1727. {
  1728.     char *comspec;
  1729.  
  1730.     if ((comspec = getenv("COMSPEC")) == NULL) {
  1731.     printf("Cannot find COMMAND.COM.\n");
  1732.     return -1;
  1733.     }
  1734.     putenv("PROMPT=Type 'EXIT' to return to FRACTINT.$_$p$g");
  1735.     return spawnl(P_WAIT, comspec, NULL);
  1736. }
  1737.  
  1738. setup_save_info()
  1739. {
  1740.    int i;
  1741.    /* set save parameters in save structure */
  1742.    strcpy(save_info.info_id, INFO_ID);
  1743.    save_info.version         = 4;
  1744.    save_info.iterations      = maxit;
  1745.    save_info.fractal_type    = fractype;
  1746.    save_info.xmin         = xxmin;
  1747.    save_info.xmax         = xxmax;
  1748.    save_info.ymin         = yymin;
  1749.    save_info.ymax         = yymax;
  1750.    save_info.creal         = param[0];
  1751.    save_info.cimag         = param[1];
  1752.    save_info.videomodeax     = videoentry.videomodeax;
  1753.    save_info.videomodebx     = videoentry.videomodebx;
  1754.    save_info.videomodecx     = videoentry.videomodecx;
  1755.    save_info.videomodedx     = videoentry.videomodedx;
  1756.    save_info.dotmode         = videoentry.dotmode;
  1757.    save_info.xdots         = videoentry.xdots;
  1758.    save_info.ydots         = videoentry.ydots;
  1759.    save_info.colors         = videoentry.colors;
  1760.    save_info.parm3         = param[2];
  1761.    save_info.parm4         = param[3];
  1762.    save_info.potential[0]    = potparam[0];
  1763.    save_info.potential[1]    = potparam[1];
  1764.    save_info.potential[2]    = potparam[2];
  1765.    save_info.rflag         = rflag;
  1766.    save_info.rseed         = rseed;
  1767.    save_info.inside         = inside;
  1768.    save_info.logmap         = LogFlag;
  1769.    save_info.invert[0]         = inversion[0];
  1770.    save_info.invert[1]         = inversion[1];
  1771.    save_info.invert[2]         = inversion[2];
  1772.    save_info.decomp[0]         = decomp[0];
  1773.    save_info.decomp[1]         = decomp[1];
  1774.    save_info.biomorph         = biomorph;
  1775.    save_info.symmetry         = forcesymmetry;
  1776.    for (i = 0; i < 16; i++)
  1777.       save_info.init3d[i] = init3d[i];
  1778.    save_info.previewfactor   = previewfactor;
  1779.    save_info.xtrans         = xtrans;
  1780.    save_info.ytrans         = ytrans;
  1781.    save_info.red_crop_left   = red_crop_left;
  1782.    save_info.red_crop_right  = red_crop_right;
  1783.    save_info.blue_crop_left  = blue_crop_left;
  1784.    save_info.blue_crop_right = blue_crop_right;
  1785.    save_info.red_bright      = red_bright;
  1786.    save_info.blue_bright     = blue_bright;
  1787.    save_info.xadjust         = xadjust;
  1788.    save_info.eyeseparation   = eyeseparation;
  1789.    save_info.glassestype     = glassestype;
  1790.    save_info.outside         = outside;
  1791.    save_info.x3rd         = xx3rd;
  1792.    save_info.y3rd         = yy3rd;
  1793.    save_info.calc_status     = calc_status;
  1794.    if (boundarytraceflag)
  1795.       save_info.stdcalcmode  = 'b';
  1796.    else if (solidguessing)
  1797.       save_info.stdcalcmode  = 'g';
  1798.    else
  1799.       save_info.stdcalcmode  = '1' + numpasses;
  1800.    save_info.distest         = distest;
  1801.    save_info.floatflag         = floatflag;
  1802.    save_info.bailout         = bailout;
  1803.    save_info.calctime         = calctime;
  1804.    save_info.trigndx[0]      = trigndx[0];
  1805.    save_info.trigndx[1]      = trigndx[1];
  1806.    save_info.trigndx[2]      = trigndx[2];
  1807.    save_info.trigndx[3]      = trigndx[3];
  1808.    save_info.finattract      = finattract;
  1809.    save_info.initorbit[0]    = initorbit.x;
  1810.    save_info.initorbit[1]    = initorbit.y;
  1811.    save_info.useinitorbit    = useinitorbit;
  1812.    save_info.periodicity     = periodicitycheck;
  1813.    for (i = 0; i < sizeof(save_info.future)/sizeof(int); i++)
  1814.       save_info.future[i] = 0;
  1815. }
  1816.  
  1817. saveanimage()
  1818. {
  1819.    double ftemp;
  1820.    zwidth = 0;
  1821.    drawbox(0);           /* clobber zoom-box */
  1822.    xxmin = sxmin;
  1823.    xxmax = sxmax;
  1824.    xx3rd = sx3rd;
  1825.    yymax = yymax;
  1826.    yymin = yymin;
  1827.    yy3rd = sy3rd;
  1828.    setup_save_info();
  1829.    diskisactive = 1;       /* flag for disk-video routines */
  1830.    savetodisk(savename);
  1831.    diskisactive = 0;       /* flag for disk-video routines */
  1832. }
  1833.  
  1834. static void reset_initparms()
  1835. {  int i;
  1836.    inititer = maxit;
  1837.    initfractype = fractype;
  1838.    initmode = adapter;
  1839.    initxmin = xxmin;
  1840.    initxmax = xxmax;
  1841.    initymin = yymin;
  1842.    initymax = yymax;
  1843.    initx3rd = xx3rd;
  1844.    inity3rd = yy3rd;
  1845.    for (i = 0; i < 4; i++)
  1846.       initparam[i] = param[i];
  1847. }
  1848.  
  1849. adjust_corner()
  1850. {  double ftemp,ftemp2;
  1851.    /* make edges very near vert/horiz exact, to ditch rounding errs and */
  1852.    /* to avoid problems when delta per axis makes too large a ratio    */
  1853.    if( (ftemp=fabs(xx3rd-xxmin)) < (ftemp2=fabs(xxmax-xx3rd)) ) {
  1854.       if (ftemp*10000 < ftemp2 && yy3rd != yymax)
  1855.      xx3rd = xxmin;
  1856.    }
  1857.    else if (ftemp2*10000 < ftemp && yy3rd != yymin)
  1858.       xx3rd = xxmax;
  1859.    if( (ftemp=fabs(yy3rd-yymin)) < (ftemp2=fabs(yymax-yy3rd)) ) {
  1860.       if (ftemp*10000 < ftemp2 && xx3rd != xxmax)
  1861.      yy3rd = yymin;
  1862.       }
  1863.    else if (ftemp2*10000 < ftemp && xx3rd != xxmin)
  1864.       yy3rd = yymax;
  1865. }
  1866.  
  1867. static void adjust_to_limits(double expand)
  1868. {  double cornerx[4],cornery[4];
  1869.    double lowx,highx,lowy,highy,limit,ftemp;
  1870.    double centerx,centery,adjx,adjy;
  1871.    int i;
  1872.    limit = 32767.99;
  1873.    if (bitshift >= 24) limit = 31.99;
  1874.    if (bitshift >= 29) limit = 3.99;
  1875.    centerx = (xxmin+xxmax)/2;
  1876.    centery = (yymin+yymax)/2;
  1877.    if (xxmin == centerx) { /* ohoh, infinitely thin, fix it */
  1878.       smallest_add(&xxmax);
  1879.       xxmin -= xxmax-centerx;
  1880.       }
  1881.    if (yymin == centery) {
  1882.       smallest_add(&yymax);
  1883.       yymin -= yymax-centery;
  1884.       }
  1885.    if (xx3rd == centerx)
  1886.       smallest_add(&xx3rd);
  1887.    if (yy3rd == centery)
  1888.       smallest_add(&yy3rd);
  1889.    /* setup array for easier manipulation */
  1890.    cornerx[0] = xxmin; cornerx[1] = xxmax;
  1891.    cornerx[2] = xx3rd; cornerx[3] = xxmin+(xxmax-xx3rd);
  1892.    cornery[0] = yymax; cornery[1] = yymin;
  1893.    cornery[2] = yy3rd; cornery[3] = yymin+(yymax-yy3rd);
  1894.    /* if caller wants image size adjusted, do that first */
  1895.    if (expand != 1.0)
  1896.       for (i=0; i<4; ++i) {
  1897.      cornerx[i] = centerx + (cornerx[i]-centerx)*expand;
  1898.      cornery[i] = centery + (cornery[i]-centery)*expand;
  1899.       }
  1900.    /* get min/max x/y values */
  1901.    lowx = highx = cornerx[0];
  1902.    lowy = highy = cornery[0];
  1903.    for (i=1; i<4; ++i) {
  1904.       if (cornerx[i] < lowx)  lowx  = cornerx[i];
  1905.       if (cornerx[i] > highx) highx = cornerx[i];
  1906.       if (cornery[i] < lowy)  lowy  = cornery[i];
  1907.       if (cornery[i] > highy) highy = cornery[i];
  1908.       }
  1909.    /* if image is too large, downsize it maintaining center */
  1910.    ftemp = highx-lowx;
  1911.    if (highy-lowy > ftemp) ftemp = highy-lowy;
  1912.    if ((ftemp = limit*2/ftemp) < 1.0)
  1913.       for (i=0; i<4; ++i) {
  1914.      cornerx[i] = centerx + (cornerx[i]-centerx)*ftemp;
  1915.      cornery[i] = centery + (cornery[i]-centery)*ftemp;
  1916.      }
  1917.    /* if any corner has x or y past limit, move the image */
  1918.    adjx = adjy = 0;
  1919.    for (i=0; i<4; ++i) {
  1920.       if (cornerx[i] > limit     && (ftemp = cornerx[i] - limit) > adjx)
  1921.      adjx = ftemp;
  1922.       if (cornerx[i] < 0.0-limit && (ftemp = cornerx[i] + limit) < adjx)
  1923.      adjx = ftemp;
  1924.       if (cornery[i] > limit     && (ftemp = cornery[i] - limit) > adjy)
  1925.      adjy = ftemp;
  1926.       if (cornery[i] < 0.0-limit && (ftemp = cornery[i] + limit) < adjy)
  1927.      adjy = ftemp;
  1928.       }
  1929.    if (calc_status == 2 && (adjx != 0 || adjy != 0))
  1930.       calc_status = 0;
  1931.    xxmin = cornerx[0] - adjx;
  1932.    xxmax = cornerx[1] - adjx;
  1933.    xx3rd = cornerx[2] - adjx;
  1934.    yymax = cornery[0] - adjy;
  1935.    yymin = cornery[1] - adjy;
  1936.    yy3rd = cornery[2] - adjy;
  1937.    adjust_corner(); /* make 3rd corner exact if very near other co-ords */
  1938. }
  1939.  
  1940. static void smallest_add(double *num)
  1941. {
  1942.    *num += *num * 5.0e-16;
  1943. }
  1944.  
  1945. static int ratio_bad(double actual, double desired)
  1946. {  double ftemp;
  1947.    if (desired != 0)
  1948.       if ((ftemp = actual / desired) < 0.9 || ftemp > 1.1)
  1949.      return(1);
  1950.    return(0);
  1951. }
  1952.  
  1953. /* read keystrokes while = specified key, return 1+count;    */
  1954. /* used to catch up when moving zoombox is slower than keyboard */
  1955. int key_count(int keynum)
  1956. {  int ctr;
  1957.    ctr = 1;
  1958.    while (keypressed() == keynum) {
  1959.       getakey();
  1960.       ++ctr;
  1961.       }
  1962.    return ctr;
  1963. }
  1964.  
  1965. /* do all pending movement at once for smooth mouse diagonal moves */
  1966. static void move_zoombox(int keynum)
  1967. {  int vertical, horizontal, getmore;
  1968.    if (boxcount == 0)
  1969.       return;
  1970.    vertical = horizontal = 0;
  1971.    getmore = 1;
  1972.    while (getmore) {
  1973.       switch (keynum) {
  1974.      case 1075:            /* cursor left */
  1975.         --horizontal;
  1976.         break;
  1977.      case 1077:            /* cursor right */
  1978.         ++horizontal;
  1979.         break;
  1980.      case 1072:            /* cursor up */
  1981.         --vertical;
  1982.         break;
  1983.      case 1080:            /* cursor down */
  1984.         ++vertical;
  1985.         break;
  1986.      case 1115:            /* Ctrl-cursor left */
  1987.         horizontal -= 5;
  1988.         break;
  1989.      case 1116:             /* Ctrl-cursor right */
  1990.         horizontal += 5;
  1991.         break;
  1992.      case 1141:            /* Ctrl-cursor up */
  1993.         vertical -= 5;
  1994.         break;
  1995.      case 1145:            /* Ctrl-cursor down */
  1996.         vertical += 5;
  1997.         break;
  1998.      default:
  1999.         getmore = 0;
  2000.      }
  2001.       if (getmore) {
  2002.      if (getmore == 2)        /* eat last key used */
  2003.         getakey();
  2004.      getmore = 2;
  2005.      keynum = keypressed();     /* next pending key */
  2006.      }
  2007.       }
  2008.    if (horizontal!=0)
  2009.       moveboxf((double)horizontal/dxsize,0.0);
  2010.    if (vertical!=0)
  2011.       moveboxf(0.0,(double)vertical*0.75/dysize);
  2012. }
  2013.  
  2014. /* displays differences between current image file and new image */
  2015. /* Bert - suggest add this to video.asm */
  2016. cmp_line(unsigned char *pixels, int linelen)
  2017. {
  2018.    static errcount;
  2019.    static FILE *fp = NULL;
  2020.    extern int rowcount;
  2021.    int col;
  2022.    int oldcolor;
  2023.    char *timestring;
  2024.    time_t ltime;
  2025.    if(fp == NULL)
  2026.       fp = fopen("cmperr",(initbatch)?"a":"w");
  2027.    if(rowcount==0)
  2028.       errcount=0;
  2029.    for(col=0;col<linelen;col++)
  2030.    {
  2031.       oldcolor=getcolor(col,rowcount);
  2032.       if(oldcolor==pixels[col])
  2033.      putcolor(col,rowcount,0);
  2034.       else
  2035.       {
  2036.      if(oldcolor==0)
  2037.         putcolor(col,rowcount,1);
  2038.      ++errcount;
  2039.      if(initbatch == 0)
  2040.         fprintf(fp,"#%5d col %3d row %3d old %3d new %3d\n",
  2041.            errcount,col,rowcount,oldcolor,pixels[col]);
  2042.       }
  2043.    }
  2044.    rowcount++;
  2045.    if(rowcount==ydots && initbatch)
  2046.    {
  2047.       time(<ime);
  2048.       timestring = ctime(<ime);
  2049.       timestring[24] = 0; /*clobber newline in time string */
  2050.       fprintf(fp,"%s compare to %s has %5d errs\n",timestring,readname,errcount);
  2051.    }
  2052.    return(0);
  2053. }
  2054.